package a1;

import java.util.List;

import a5.common.ProgramCursor;
import a5.common.Token;
import a5.grammar.interfaces.Grammar;

import com.google.inject.Inject;

public class Parser {
	private Grammar grammar;
	/**
	 * <pre>
	 * Creates a new Interpreter for parsing the argument {@link a5.grammar.interfaces.Grammar Grammar} 
	 * using the argument {@link a5.environment.Environment Environment}. 
	 * 
	 * This constructor uses the {@code @Inject} annotation for use with Google Guice (or javax.inject).
	 * To make use of this constructor, a new {@code Injector} instance should be bound to a {@code Module}
	 * and then invoke the method {@code injector.createInstance(Interpreter.class) }. 
	 * 
	 * To see this in action, run A5Injected.java
	 * </pre>
	 * 
	 * @param environment
	 * The {@link a5.environment.Environment Environment} to which this interpreter will be bound.
	 */
	@Inject
	public Parser(Grammar grammar){
		this.grammar = grammar;
	}
	
	/**
	 * Parses the argument program and returns the result of the parse as a {@code String}
	 * 
	 * @param program
	 * A {@code String} representation of a program to parse.  
	 *  
	 * @return
	 * The {@code String} result of the parse of the argument program. 
	 */
	public String parse(String program){
		// Tokenize the program and append an end of input token.
		// The end of input token will be used after interpretation to verify that the
		// program ended at the expected location.
		List<Token> tokens = Token.tokenize(program);
		tokens.add(new Token(Token.END_OF_INPUT_TYPE));
		ProgramCursor cursor = new ProgramCursor(tokens);
		
		// Perform the parse. The grammar defines how the productions should be applied.
		String result = grammar.parse(cursor).toString();
		
		// If the program is in the grammar (whatever that may be), then the end of input token
		// should be the next token.
		cursor.match(Token.END_OF_INPUT_TYPE);
		
		return result;
	}
}
